using System;
using System.Collections.Generic;

using System.Text;
using System.IO;
using org.ngwt.user.server.rpc.impl;
using System.Web;

namespace org.ngwt.user.server.rpc
{
    /**
     * API for loading a {@link SerializationPolicy}.
     */
    public static class SerializationPolicyLoader
    {
        /**
         * Default encoding for serialization policy files.
         */
        public static String SERIALIZATION_POLICY_FILE_ENCODING = "UTF-8";

        private static String FORMAT_ERROR_MESSAGE = "Expected: className, [true | false]";



        /**
         * Returns the serialization policy file name from the from the serialization
         * policy strong name.
         * 
         * @param serializationPolicyStrongName the serialization policy strong name
         * @return the serialization policy file name from the from the serialization
         *         policy strong name
         */
        public static String getSerializationPolicyFileName(String serializationPolicyStrongName) 
        {
          return serializationPolicyStrongName + ".gwt.rpc";
        }

        /**
         * Loads a SerializationPolicy from an input stream.
         * 
         * @param inputStream stream to load from
         * @return a {@link SerializationPolicy} loaded from the input stream
         * 
         * @throws IOException if an error occurs while reading the stream
         * @throws ParseException if the input stream is not properly formatted
         * @throws ClassNotFoundException if a class specified in the serialization
         *           policy cannot be loaded
         */
        public static SerializationPolicy loadFromStream(Stream inputStream)
        {
          if (inputStream == null) {
            throw new NullReferenceException("inputStream");
          }

          Dictionary<Type, bool> whitelist = new Dictionary<Type, bool>();

          StreamReader br = new StreamReader(inputStream,new System.Text.UTF8Encoding());
          //BufferedReader br = new BufferedReader(isr);

          String line = br.ReadLine();
          int lineNum = 1;
          while (line != null) {
            line = line.Trim();
            if (line.Length > 0) {
              String[] components = line.Split(',');

                if (components.Length != 2) {
                    throw new Exception(FORMAT_ERROR_MESSAGE +  " on line:" + lineNum);
              }

              String binaryTypeName = components[0].Trim();
              String instantiable = components[1].Trim();

                if (binaryTypeName.Length == 0 || instantiable.Length == 0) {
                    throw new ParseException(FORMAT_ERROR_MESSAGE, lineNum);
              }
              binaryTypeName = JavaDotNetClassTrans.JavaToNet(binaryTypeName);

              //ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
              //Type clazz = Class.forName(binaryTypeName, false, contextClassLoader);
              Type clazz = Type.GetType(binaryTypeName);
              if (clazz == null)
                  clazz = RPC.FindType(binaryTypeName);
              // TODO: Validate the instantiable string better.
              whitelist.Add(clazz, Boolean.Parse(instantiable));
            }

            line = br.ReadLine();
            lineNum++;
          }

          return new StandardSerializationPolicy(whitelist);
        }
    }
}
